// Learn cc.Class:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/class.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/class.html
// Learn Attribute:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/en/scripting/life-cycle-callbacks.html

let MSG_TYPE = {
    OPEN_CHESS: "OPEN_CHESS",//打开棋子
    EAT: "EAT",//吃棋
    MOVE: "MOVE",//移动棋子
};

let GAME_MEMBER_NUM = 2;

var RedBlueGame = require("./RedBlueGame");

let DIRECTION = {
    left: 0,
    top: 1,
    right: 2,
    bottom: 3,
};

cc.Class({
    extends: RedBlueGame,

    properties: {
        chessPrefab: {
            type: cc.Prefab,
            default: null,
        },
        resultPrefab: {
            type: cc.Prefab,
            default: null
        },
        boardNode: {
            type: cc.Node,
            default: null
        },
        //轮到自己走棋
        forSelfNode: {
            type: cc.Node,
            default: null
        },
        //轮到对方走棋
        forRivalNode: {
            type: cc.Node,
            default: null
        },
        selfColorNode: {
            type: cc.Node,
            default: null,
        },
        rivalColorNode: {
            type: cc.Node,
            default: null,
        }

    },

    // LIFE-CYCLE CALLBACKS:

    start() {
        this.forSelfNode.active = false;
        this.forRivalNode.active = false;
        this._super();
    },

    onPrepare() {
        this.started = true;
        this.selfTip = this.node.getChildByName("self_tip");
        this.rivalTip = this.node.getChildByName("rival_tip");
        this.selfNameNode = this.node.getChildByName("self_name");
        this.rivalNameNode = this.node.getChildByName("rival_name");

        this._super();
    },


    //由子类继承, 生成游戏数据
    onGenerateGameData() {
        let gameData = this._super();
        //server生成游戏数据， client接受游戏数据
        let allCheses = [{ type: "elephant", name: "象", belong: "black", opened: false, alive: true },
        { type: "lion", name: "狮", belong: "black", opened: false, alive: true },
        { type: "tiger", name: "虎", belong: "black", opened: false, alive: true },
        { type: "leopard", name: "豹", belong: "black", opened: false, alive: true },
        { type: "dog", name: "狗", belong: "black", opened: false, alive: true },
        { type: "wolf", name: "狼", belong: "black", opened: false, alive: true },
        { type: "cat", name: "猫", belong: "black", opened: false, alive: true },
        { type: "mouse", name: "鼠", belong: "black", opened: false, alive: true },

        { type: "elephant", name: "象", belong: "white", opened: false, alive: true },
        { type: "lion", name: "狮", belong: "white", opened: false, alive: true },
        { type: "tiger", name: "虎", belong: "white", opened: false, alive: true },
        { type: "leopard", name: "豹", belong: "white", opened: false, alive: true },
        { type: "dog", name: "狗", belong: "white", opened: false, alive: true },
        { type: "wolf", name: "狼", belong: "white", opened: false, alive: true },
        { type: "cat", name: "猫", belong: "white", opened: false, alive: true },
        { type: "mouse", name: "鼠", belong: "white", opened: false, alive: true },
        ];

        //棋盘中的每个格子分配旗子
        let chesesLayout = [];
        for (let i = 0; i < 4; i++) {
            let row = [];
            chesesLayout.push(row);
            for (let j = 0; j < 4; j++) {
                let witch = Math.floor(cc.rand()) % allCheses.length;
                let chessDetail = allCheses[witch];
                allCheses.splice(witch, 1);
                row.push(chessDetail);

            }
        }

        gameData.chesesLayout = chesesLayout;
        return gameData;
    },

    //获取当前游戏所有数据, 以用于同步重新连接时的游戏数据
    onGetGameData() {
        let gameData = this._super();
        //棋盘中的每个格子分配旗子
        let chesesLayout = [];
        for (let i = 0; i < this.chesesLayout.length; i++) {
            let row = [];
            chesesLayout.push(row);
            for (let j = 0; j < this.chesesLayout[0].length; j++) {
                let chessDetail = null;
                if (this.chesesLayout[i][j].chess) {
                    let chess = this.chesesLayout[i][j].chess;
                    chessDetail = {
                        type: chess.type, name: chess.name, belong: chess.belong, opened: chess.isOpened(), alive: chess.alive
                    }
                }

                row.push(chessDetail);
            }
        }
        gameData.chesesLayout = chesesLayout;
        return gameData;
    },

    loadGame(gameData) {
        this._super(gameData);
        this.chesesLayout = gameData.chesesLayout;
        this.chesesNodeGenerate();
        this.onColor(this.step);
    },

    //接受对手消息, 子类重写， 调用this._super(), 返回false时，处理没有被消费的消息
    onRivalMessage(msg) {
        if (!this._super(msg)) {
            let data = JSON.parse(msg.msg);
            switch (data.type) {
                case MSG_TYPE.OPEN_CHESS:
                    //对手翻开棋子
                    this.openChessByRial(data.row, data.colume);
                    break;

                case MSG_TYPE.EAT:
                    this.eatByRival(data.fromRow, data.fromColume, data.toRow, data.toColume);
                    break;

                case MSG_TYPE.MOVE:
                    this.move(data.nodeRow, data.nodeColume, data.toRow, data.toColume, false);
                    break;


            }
        }

    },

    //颜色分配
    colorAllocation(selfColor, rivalColor) {
        //固定自己是蓝色，对手红色展示
        // cc.loader.loadRes("Texture/top/head-boards/head-board-" + selfColor, cc.SpriteFrame, function (err, spriteFrame) {
        //     if (err) {
        //         cc.log(err);
        //     } else {
        //         this.selfColorNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
        //     }
        // }.bind(this));

        // cc.loader.loadRes("Texture/top/head-boards/head-board-" + rivalColor, cc.SpriteFrame, function (err, spriteFrame) {
        //     if (err) {
        //         cc.log(err);
        //     } else {
        //         this.rivalColorNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
        //     }
        // }.bind(this));

    },

    //棋子是否属于我
    belongToMe(chess) {
        return chess.belong == this.color;
    },

    //轮到color方下棋, 必须调用this._super(gameData);
    onColor(c) {
        if (c == this.color) {
            this.forSelfNode.active = true;
            this.forRivalNode.active = false;
        } else {
            this.forSelfNode.active = false;
            this.forRivalNode.active = true;
        }

        var self = this;
        this.chesesLayout.forEach(row => {
            row.forEach(cell => {
                if (cell.chess && cell.chess.alive) {
                    if (self.myStep()) {
                        if (self.belongToMe(cell.chess) || !cell.chess.isOpened()) {
                            // cell.chess.node.addComponent("outline");
                            //显示上固定自己是蓝色方
                            cell.chess.setBorder("blue");
                        }
                    } else {
                        // cell.chess.node.removeComponent("outline");
                        cell.chess.setBorder(null);
                    }

                }
            });
        });

        if (this.needGuide && this.myStep()) {
            for (let i = 0; i < this.chesesLayout.length; i++) {
                if(!this.chesesLayout[i][0].chess.isOpened()){
                    this.guide(this.chesesLayout[i][0].chess);
                    this.needGuide = false;
                    return;
                }
            }
        }

        this._super(c);
    },

    getCell(row, colume, direction) {
        switch (direction) {
            case DIRECTION.left:
                colume -= 1;
                break;
            case DIRECTION.top:
                row += 1;
                break;
            case DIRECTION.right:
                colume += 1;
                break;
            case DIRECTION.bottom:
                row -= 1;
                break;
            default:
                break;
        }
        if (row >= 0 && row < 4 && colume >= 0 && colume < 4) {
            return { row, colume };
        }
        return null;
    },

    onDestroy(){
        cc.log("游戏场景销毁 game onDestroy");
        this._super();
        if(this.robotTimeout) {
            clearTimeout(this.robotTimeout);
        }
    },

    //轮到机器人操作
    onRobotStep() {
        //机器人随机1~4秒内走棋
        this.robotTimeout = setTimeout(function () {
            let couldEat = [];
            let fightOut = [];//可以拼了的棋子
            if(this.chesesLayout == null) {
                cc.log("Error chesesLayout is null");
                return;
            }
            //1.吃棋 
            for (let i = 0; i < this.chesesLayout.length; i++) {
                for (let j = 0; j < this.chesesLayout[0].length; j++) {
                    let chess = this.chesesLayout[i][j].chess;
                    //属于对手（机器人）的棋子
                    if (chess && chess.isOpened() && chess.alive && !this.belongToMe(chess)) {
                        for (let z = 0; z < 4; z++) {
                            let cell = this.getCell(i, j, z);
                            if (cell) {
                                let chessTwo = this.chesesLayout[cell.row][cell.colume].chess;
                                //属于玩家的棋子, 并且可以吃棋
                                if (chessTwo.isOpened() && chessTwo.alive && this.belongToMe(chessTwo)) {
                                    let stronger = this.stronger(chess, chessTwo);
                                    if (stronger > 0) {
                                        couldEat.push({ target: { row: i, colume: j }, couldFightOut: cell })
                                    } else if (stronger == 0) {
                                        fightOut.push({ target: { row: i, colume: j }, couldFightOut: cell });
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (couldEat.length > 0) {
                let randEat = couldEat[Math.floor(cc.rand()) % couldEat.length];
                this.eatByRival(randEat.target.row, randEat.target.colume, randEat.couldFightOut.row, randEat.couldFightOut.colume);
                cc.log("robot eat");
                return;
            }

            //2.翻棋
            let couldOpen = [];
            for (let i = 0; i < this.chesesLayout.length; i++) {
                for (let j = 0; j < this.chesesLayout[0].length; j++) {
                    let chess = this.chesesLayout[i][j].chess;
                    //未翻开的棋子
                    if (chess && !chess.isOpened()) {
                        couldOpen.push({ row: i, colume: j });
                    }
                }
            }
            if (couldOpen.length > 0) {
                let randOpen = couldOpen[Math.floor(cc.rand()) % couldOpen.length];
                this.openChessByRial(randOpen.row, randOpen.colume);
                cc.log("robot open");
                return;
            }

            //3.拼棋子
            if (fightOut.length > 0) {
                let randEat = fightOut[Math.floor(cc.rand()) % fightOut.length];
                this.eatByRival(randEat.target.row, randEat.target.colume, randEat.couldFightOut.row, randEat.couldFightOut.colume);
                cc.log("robot fight out");
                return;
            }

            //4.将大棋子向小棋子方向移动一步
            let noDangerMove = [];
            let goAfter = [];//追玩家的小旗子
            for (let i = 0; i < this.chesesLayout.length; i++) {
                for (let j = 0; j < this.chesesLayout[0].length; j++) {
                    let chess = this.chesesLayout[i][j].chess;
                    //属于对手（机器人）的棋子
                    if (chess && chess.alive && !this.belongToMe(chess)) {
                        for (let z = 0; z < 4; z++) {
                            let couldMove = this.getCell(i, j, z);
                            if (couldMove && this.isEmpty(couldMove.row, couldMove.colume)) {
                                let haveSmaller = false;
                                let haveBigger = false;
                                //可以移动到这个位置
                                for (let k = 0; k < 4; k++) {
                                    //看一下这个周围有没有可以吃自己的，否则就是送棋子给别人吃了
                                    let arroundCell = this.getCell(couldMove.row, couldMove.colume, k);
                                    if (arroundCell) {
                                        let arroundChess = this.chesesLayout[arroundCell.row][arroundCell.colume].chess;
                                        if (arroundChess.alive && this.belongToMe(arroundChess)) {
                                            //有玩家的棋子
                                            let stronger = this.stronger(chess, arroundChess);
                                            if (stronger > 0) {
                                                //机器人的棋子比玩家棋子大，预期可吃子
                                                haveSmaller = true;
                                            } else if (stronger < 0) {
                                                //不能到这个位子来
                                                haveBigger = true;
                                            }
                                        }
                                    }
                                }

                                if (haveBigger) {
                                    //移动到的目标位置，会被敌人吃掉
                                } else if (haveSmaller) {
                                    //没有危险，并且还能追别人的小棋子
                                    goAfter.push({ target: { row: i, colume: j }, couldMove: couldMove });
                                } else {
                                    //收集没有危险的移动
                                    noDangerMove.push({ target: { row: i, colume: j }, couldMove: couldMove });
                                }
                            }
                        }
                    }
                }
            }
            if (goAfter.length > 0) {
                let randMove = goAfter[Math.floor(cc.rand()) % goAfter.length];
                this.move(randMove.target.row, randMove.target.colume, randMove.couldMove.row, randMove.couldMove.colume);
                cc.log("robot go after");
                return;
            }

            //5.随便走一步没有危险的
            if (noDangerMove.length > 0) {
                let randMove = noDangerMove[Math.floor(cc.rand()) % noDangerMove.length];
                this.move(randMove.target.row, randMove.target.colume, randMove.couldMove.row, randMove.couldMove.colume);
                cc.log("robot move");
            }

            cc.log("robot no step");
        }.bind(this), (cc.random0To1() * 3 + 1) * 1000);
    },

    //轮到地方下棋时，判断我方是否胜利，胜者向服务端报告结果
    checkGameOver() {
        let ownChesesNum = 0, rivalChesesNum = 0;
        for (let i = 0; i < this.chesesLayout.length; i++) {
            for (let j = 0; j < this.chesesLayout[0].length; j++) {
                if (!this.chesesLayout[i][j].chess.isOpened()) {
                    return false;
                }
                if (this.chesesLayout[i][j].chess.alive) {
                    if (this.belongToMe(this.chesesLayout[i][j].chess)) {
                        ownChesesNum += 1;
                    } else {
                        rivalChesesNum += 1;
                    }
                }
            }
        }
        if (ownChesesNum == 0 && rivalChesesNum == 0) {
            this.drawn();
        } else if (ownChesesNum == 0) {
            this.defeat();
        } else if (rivalChesesNum == 0) {
            this.victory();
        }
    },

    //生成棋子视觉节点, 包括reload
    chesesNodeGenerate() {
        for (let i = 0; i < 4; i++) {
            for (let j = 0; j < 4; j++) {
                if (this.chesesLayout[i][j].chess) {
                    this.chesesLayout[i][j].chess.node.destroy();
                    this.chesesLayout[i][j].chess = null;
                }

                let chessDetail = this.chesesLayout[i][j];
                if (chessDetail) {
                    let chessNode = cc.instantiate(this.chessPrefab);
                    let chess = chessNode.getComponent("chess");
                    this.chesesLayout[i][j].chess = chess;
                    chessNode.x = this.chesesLayout[i][j].x;
                    chessNode.y = this.chesesLayout[i][j].y;
                    chess.row = i;
                    chess.colume = j;
                    this.boardNode.addChild(chessNode);

                    let belongToMe = false;
                    if (this.color == chessDetail.belong) {
                        //固定自己的显示颜色为蓝色
                        belongToMe = true;
                    }
                    chess.init(chessDetail.type, chessDetail.name, chessDetail.belong, belongToMe);

                    if (chessDetail.opened) {
                        chess.open();
                    }

                    let clickEventHandler = new cc.Component.EventHandler();
                    clickEventHandler.target = this.node;
                    clickEventHandler.component = "game";
                    clickEventHandler.handler = "onChesesClick";

                    let button = chessNode.getComponent(cc.Button);
                    button.clickEvents.push(clickEventHandler);

                    // this.chessW = chessNode.width;
                    // this.chessH = chessNode.height;
                }
            }
        }
    },

    chooseChess(chess) {
        if (chess == this.checked && chess != null) {
            this.checked.choose(false);
            this.checked = null;
        }
        if (this.checked) {
            this.checked.choose(false);
            this.checked = null;
        }
        if (chess) {
            chess.choose(true);
            this.checked = chess;
        }
    },

    toast(type) {
        // if (this.toastNode && this.toastNode.isRunning()) {
        //     this.toastNode.destroy();
        // }
        // this.toastNode = cc.instantiate(this.toastPrefab);
        // this.node.addChild(this.toastNode);
        // let toastAnimation = this.toastNode.getComponent(cc.Animation);
        // toastAnimation.playAdditive(type);
        // toastAnimation.playAdditive("toast");
        // toastAnimation.on("finished", function () {
        //     this.toastNode.destroy();
        // }, this);
        this._super(type);
    },

    //打开棋子
    openChess(chess) {
        chess.open();
        this.changePlayer(false);

        this.checkGameOver();
    },

    //对手打开棋子
    openChessByRial(row, colume) {
        this.chesesLayout[row][colume].chess.open(function () {
            this.changePlayer(false);
        }.bind(this));
    },

    //空位置放置的是一个死棋子
    isEmpty(row, colume) {
        return !this.chesesLayout[row][colume].chess.alive;
    },

    onChesesClick(event) {
        if (!this.myStep()) {
            this.toast("等待对手操作");
            return;
        }

        let chessNode = event.target;
        let chess = chessNode.getComponent("chess");
        //let chess = chessNode.getComponent("chess");
        //chess.show();
        if (!chess.isOpened()) {
            this.openChess(chess);

            this.cancleGuide();

            if (this.checked) {
                this.checked.choosed(false, true);
                this.checked = null;
            }
        } else {
            if (!this.checked) {
                //空位棋子
                if (!chess.alive) {
                    return;
                }

                //初次选中，只能选中自己方的棋子
                if (!this.belongToMe(chess)) {
                    //TODO 提示不能操作对方棋子
                    this.toast("不能操作对手的棋子哦");
                } else {
                    //选中
                    this.checked = chess;
                    this.checked.choosed(true);
                }
            } else {
                if (this.checked == chess) {
                    //点击已经选中的
                    this.checked.choosed(false, true);
                    this.checked = null;
                    return;
                }

                if (!chess.alive) {
                    if (!this.couldMove(this.checked.row, this.checked.colume, chess.row, chess.colume)) {
                        this.checked.choosed(false);
                        this.checked = null;
                        return false;
                    }

                    //移动
                    this.checked.choosed(false);
                    this.move(this.checked.row, this.checked.colume, chess.row, chess.colume, true, function () {
                        this.checked = null;
                    }.bind(this));

                    return;
                }

                //如果已经选中， 当前选中的是敌方棋子，则吃旗
                if (!this.belongToMe(chess)) {
                    if (this.couldEat(this.checked, chess)) {
                        this.checked.choosed(false);
                        this.eat(this.checked, chess, true, function () {
                            this.checked = null;
                        }.bind(this));

                    } else {
                        // this.waitingOperate();
                    }
                } else {
                    //切换选中
                    this.checked.choosed(false);
                    this.checked = chess;
                    chess.choosed(true);
                }
            }
        }

    },

    replaceCell(one, two) {
        let oneRow = one.row, oneColume = one.colume, twoRow = two.row, twoColume = two.colume;

        this.chesesLayout[oneRow][oneColume].chess = two;
        this.chesesLayout[twoRow][twoColume].chess = one;

        one.colume = twoColume;
        one.row = twoRow;

        two.colume = oneColume;
        two.row = oneRow;

    },

    replase(one, two, callback) {
        let oneRow = one.row, oneColume = one.colume, twoRow = two.row, twoColume = two.colume;
        if (this.couldMove(oneRow, oneColume, twoRow, twoColume)) {
            let oneX = one.node.x, oneY = one.node.y;
            one.move(two.node.x, two.node.y, function () {
                two.move(oneX, oneY);
                if (callback) callback();
            });

            this.replaceCell(one, two);
        }
    },

    //移动，send要不要通知对方
    move(nodeRow, nodeColume, toRow, toColume, send, callback) {
        let one = this.chesesLayout[nodeRow][nodeColume].chess;
        let two = this.chesesLayout[toRow][toColume].chess;
        this.replase(one, two, callback);
        if (send) {
            this.sendMessage({ type: MSG_TYPE.MOVE, nodeRow: nodeRow, nodeColume: nodeColume, toRow: toRow, toColume: toColume });
        }
        this.changePlayer(false);
    },


    //吃棋
    eat(from, to, send, callback) {
        if (send) {
            this.sendMessage({ type: MSG_TYPE.EAT, fromRow: from.row, fromColume: from.colume, toRow: to.row, toColume: to.colume });
        }

        let fromX = from.node.x;
        let fromY = from.node.y;
        from.move(to.node.x, to.node.y, function () {
            let stronger = this.stronger(from, to);
            if (stronger > 0) {
                to.die(function () {
                    to.node.x = fromX;
                    to.node.y = fromY;
                    this.replaceCell(from, to);

                    if (callback) callback();
                    this.checkGameOver();
                }.bind(this));
                from.eat();
                //TODO 这里没有吃的冒烟动画， 是因为与非选中动画冲突了, 解决办法， unselect的动画放在move中，保证动画完了之后执行eat动画
            } else if (stronger == 0) {
                to.eat();
                let dieNum = 0;
                let dieOver = function () {
                    dieNum++;
                    if (dieNum == 2) {
                        to.node.x = fromX;
                        to.node.y = fromY;
                        this.replaceCell(from, to);

                        if (callback) callback();
                        this.checkGameOver();
                    }
                }.bind(this);
                to.die(dieOver);
                from.die(dieOver);
            } else {
                from.die(function () {
                    from.node.x = fromX;
                    from.node.y = fromY;
                    to.eat();
                    if (callback) callback();
                    this.checkGameOver();
                }.bind(this));
            }
        }.bind(this));

        this.changePlayer(true);
    },

    eatByRival(fromRow, fromColume, toRow, toColume) {
        this.eat(this.chesesLayout[fromRow][fromColume].chess, this.chesesLayout[toRow][toColume].chess, false);
    },

    couldMove(fromX, fromY, toX, toY) {
        if (!((fromX == toX && Math.abs(fromY - toY) == 1) ||
            (fromY == toY && Math.abs(fromX - toX) == 1))) {
            return false;
        }
        return true;
    },

    couldEat(from, to) {
        if (from.belong == to.belong) {
            return false;
        }

        if (!from.alive || !to.alive) {
            return false;
        }

        if (!this.couldMove(from.row, from.colume, to.row, to.colume)) {
            return false;
        }

        return true;

    },

    //正数表示from 比 to 更厉害，  0表示一样， 负数表示 from 比 to 小
    stronger(from, to) {
        this.types = ["elephant", "lion", "tiger", "leopard", "wolf", "dog", "cat", "mouse"];

        let fromIndex = this.types.indexOf(from.type);
        let toIndex = this.types.indexOf(to.type);
        if (fromIndex == 0 && toIndex == this.types.length - 1) {
            //象比老鼠小
            return -1;
        } else if (fromIndex == this.types.length - 1 && toIndex == 0) {
            //老鼠比象大
            return 1;
        } else {
            return toIndex - fromIndex;
        }
    },

    //新手引导
    guide(chess) {
        setTimeout(function () {
            this.guideNode = cc.instantiate(this.guidePrefab);
            this.node.addChild(this.guideNode);
            let guideChessNode = this.guideNode.getChildByName("chess");

            // fromNode.setPosition(guideNode.convertToNodeSpaceAR(one.node.convertToWorldSpaceAR(cc.p(0, 0))));
            guideChessNode.setPosition(chess.node.getParent().convertToWorldSpaceAR(chess.node));
            let ani = this.guideNode.getComponent(cc.Animation);
            ani.play("guide");
            ani.on("finished", function () {
                this.cancleGuide();
            }.bind(this))

        }.bind(this), 1000);

    },

    //取消引导
    cancleGuide() {
        if (this.guideNode) {
            this.guideNode.destroy();
            this.guideNode = null;
        }
    },

    //打开规则说明，就取消引导
    mzOpenRule() {
        this.cancleGuide();
        this._super();

    },
    // update (dt) {},
});
